#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import re
from plotchart import *
from math import exp,log
import numpy as np
from os.path import join as joinpath

def usage():
    print '''\
Usage: %s -c <configuration-file>
''' % sys.argv[0]
    sys.exit(1)

def getopts(list, flags):
    import getopt
    try:
        opts, args = getopt.getopt(list, flags)
    except getopt.GetoptError:
        usage()

    return opts, args

work_dir = 'spec_workdir'
isa = 'trips'
inputset = 'ref'
home = os.environ['HOME']

result_dir = os.path.join(home, work_dir, 'backup')

output_dir = os.path.join(home, work_dir, 'figs')

int_benchmarks = ['gzip','vpr','gcc','mcf',
                  'perlbmk',
                  'crafty','parser','gap','vortex',
#                  'crafty','gap','vortex',
                  'bzip2','twolf',]

float_benchmarks = ['wupwise','swim',
                    'mgrid','applu','mesa','art',
                    'equake','ammp','apsi'] 

class TempStat(object):
    stat = float(0.0)
    def __init__(self,bname,sname,config,**kwargs):
        self.bname = bname
        self.sname = sname
        stats_file = os.path.join(result_dir, 'type_only.csv')

        tmp_f = open(stats_file, 'r')
        if len(tmp_f.readlines()) == 0:
            sys.exit("Empty stats file:%s" % stats_file)

        tmp_f.close()

        tmp_pattern = config.split('_')[0]
        for line in open(stats_file):
            l = line.split(',')
            if not l:
                continue
            if l[0] == tmp_pattern:
                self.stat = float(l[int(sname)])
                break

    def data(self):
        return self.stat

class Stat(object):
    stat = float(0.0)
    def __init__(self,bname,sname,config,mode='normal',**kwargs):
        self.bname = bname
        self.sname = sname
        stats_file = os.path.join(result_dir, config,
                                  'stats', bname + '.txt')

        tmp_f = open(stats_file, 'r')
        if len(tmp_f.readlines()) == 0:
            sys.exit("Empty stats file: %s" % stats_file)

        tmp_f.close()

        if mode == 'normal':
            for line in open(stats_file):
                l = line.split()
                if not l:
                    continue
                l[0] = l[0].replace('system0','system')
                if l[0] == sname:
                    self.stat = float(l[1])
                    break
        elif mode == 'pdf':
            for line in open(stats_file):
                l = line.split()
                if not l:
                    continue
                l[0] = l[0].replace('system0','system')
                if l[0] == sname:
                    self.stat = (float(l[2].rstrip('%')) / 100.0)
                    break
        elif mode == 'cdf':
            for line in open(stats_file):
                l = line.split()
                if not l:
                    continue
                l[0] = l[0].replace('system0','system')
                if l[0] == sname:
                    self.stat = (float(l[3].rstrip('%')) / 100.0)
                    break
        else:
            sys.exit("Unknown mode while reading stats")

    
    def data(self):
        return self.stat

def GeometryMean(X):

   return exp(sum([log(x) for x in X]) / len(X))

def ArithmaticMean(X):

    return float(sum([float(x) for x in X]) / float(len(X)))

class Options:pass

if __name__ == '__main__':
    import getpass

    options = Options()
    options.conf = None
   
    opts, args = getopts(sys.argv[1:],'-c:')

    for o,a in opts:
        if o == '-c':
            options.conf = a

    if not options.conf :
        sys.exit('Where is your configuration file?')

    if not os.path.isdir(output_dir):
        os.makedirs(output_dir)

    if not os.path.isdir(result_dir):
        print 'Can not find the directory for stats: %s' % result_dir
        sys.exit(1)

    print 'Read results from %s' % result_dir
    print 'Put figures to %s' % output_dir

    for line in open(options.conf) :
        drawing_options = line.split()

        draw = False

        if not drawing_options or drawing_options[0] != '!' :
            continue

        if drawing_options[1] == 'SSMP':

            statistics = drawing_options[2]
            base_stat_name = statistics
            benchmark_hint = drawing_options[3]
            configurations = drawing_options[4]
            comments = drawing_options[5]

            configurations = configurations.split(',')

            if len(statistics.split(',')) > 1:
                sys.exit('Only one statitics is supported in SSMP mode')

            comments = comments.split(',')

            stat_mode = comments[2]

            stat_step = 1

            chart = PlotChart()
#            chart.xticks = comments

            if comments[0] == 'inc' or comments[0] == 'powerof2':
                if len(comments) < 5:
                    sys.exit('''SSMP option need 5 comments seperated by
                        comma, the first one is the key word 'inc or
                        powerof2',
                        the second one is the starting number, the
                        third is the ending number, the fourth is the
                        incremental step, and the final one is the
                        statistic name''')
                else:
                    stat_start = int(comments[1])
                    stat_end = int(comments[2])
                    stat_step = int(comments[3])
                    stat_name = comments[4]
                    
                    temp_confs = []
                    for conf in configurations:
                        if conf == 'simple_to_perfect_type':
                            temp_confs.extend([conf]*((stat_start - \
                                    stat_end) / stat_step) + 1)
                        elif comments[0] == 'inc':
                            temp_confs.extend([conf + '_' + stat_name +\
                            '_' + str(i) for i in range(stat_start, stat_end,\
                                stat_step)])
                        elif comments[0] == 'powerof2':
                            temp_confs.extend([conf + '_' + stat_name +\
                            '_' + str(2**i) for i in range(stat_start, stat_end,\
                                stat_step)])

                    configurations = temp_confs

                    chart.xticks = [str(i) for i in range(stat_start,\
                        stat_end, stat_step)]

#                    chart.xticks = ['(%s,%s)' % (str(2**i),\
#                        str(2**(stat_end-i-1))) for i in\
#                            range(stat_start, stat_end, stat_step)]
                    print chart.xticks

            elif len(comments) != conf_num:
                sys.exit('''SSMP option need %d comments seperated by
                        comma''' % conf_num)

            benchmarks = []
            if benchmark_hint == 'all':
                benchmarks = int_benchmarks + float_benchmarks 
            elif benchmark_hint == 'int':
                benchmarks = int_benchmarks
            elif benchmark_hint == 'fp':
                benchmarks = float_benchmarks 
            else :
                benchmarks = benchmark_hint.split(',')

            conf_num = len(configurations)

            data = np.zeros(len(benchmarks) * conf_num)
            extra = np.zeros(len(benchmarks) * conf_num)
            
            data.shape = (len(benchmarks), conf_num)
            extra.shape = (len(benchmarks), conf_num)

#            chart.xticks = []
            chart.legend = []
            chart.xlabel = unicode(comments[-2].replace('_', ' '), 'utf-8')
            chart.ylabel = unicode(comments[-3].replace('_', ' '), 'utf-8')
            #chart.xlabel = u"资源"

            print "Drawing %s for %s" % (base_stat_name, benchmark_hint)

#            chart.xticks = comments

            for i,bench in enumerate(benchmarks):

                for j,conf in enumerate(configurations):

                    if statistics == 'mpki':
                        mispredicts = Stat(bench,
                                'system.cpu.commit.branchMispredicts', 
                                conf,
                                'normal')
                        commit_insts = Stat(bench,
                                'system.cpu.committedInsts_total',
                                conf,
                                'normal')
                        data[i,j] = mispredicts.data() /\
                            (commit_insts.data() / 1000.0)
                    elif statistics == 'mpki_exit':
                        mispredicts = Stat(bench,
                                'system.cpu.commit.exitMispredicts', 
                                conf,
                                'normal')
                        commit_insts = Stat(bench,
                                'system.cpu.committedInsts_total',
                                conf,
                                'normal')
                        data[i,j] = mispredicts.data() /\
                            (commit_insts.data() / 1000.0)

                    elif statistics == 'mpki_type':
                        mispredicts = Stat(bench,
                                'system.cpu.commit.branchTypeOnlyMispredicts', 
                                conf,
                                'normal')
                        commit_insts = Stat(bench,
                                'system.cpu.committedInsts_total',
                                conf,
                                'normal')
                        data[i,j] = mispredicts.data() /\
                            (commit_insts.data() / 1000.0)
 
                    else:
                        stat = Stat(bench, statistics, conf, 'normal')
                        data[i,j] = stat.data()

                chart.legend.append(bench)

            draw = True
            
        if drawing_options[1] == 'SMSP':

            base_stat_name = drawing_options[2]
            benchmark_hint = drawing_options[3]
            configurations = drawing_options[4]
            comments = drawing_options[5]

            configurations = configurations.split(',')

            if len(configurations) != 1:
                sys.exit('''SMSP option only support just ONE configuration, no
                        more, no less''')
            
            comments = comments.split(',')

            if len(comments) < 5 :
                sys.exit('''SMSP option need at least five comments seperated by comma''')

            stat_step = int(comments[0])
            stat_number = int(comments[1])
            stat_mode = comments[2]

            benchmarks = []
            if benchmark_hint == 'all' :
                benchmarks = int_benchmarks + float_benchmarks 
            elif benchmark_hint == 'int':
                benchmarks = int_benchmarks
            elif benchmark_hint == 'fp':
                benchmarks = float_benchmarks 
            else :
                benchmarks = benchmark_hint.split(',')

            data = np.zeros(len(benchmarks)*stat_number)
            extra = np.zeros(len(benchmarks)*stat_number)
            
            data.shape = (len(benchmarks),stat_number)
            extra.shape = (len(benchmarks),stat_number)

            chart = PlotChart()
#            chart.xticks = []
            chart.legend = []
#            chart.xlabel = base_stat_name
#            chart.ylabel = stat_mode
            chart.xlabel = unicode(comments[-2].replace('_', ' '), 'utf-8')
            chart.ylabel = unicode(comments[-3].replace('_', ' '), 'utf-8')

            print "Drawing %s for %s" % (base_stat_name, benchmark_hint)

            for i,bench in enumerate(benchmarks):

                for j in range(len(data[i])):
                    if j != len(data[i])-1:
                        stat_name = base_stat_name + '::' + '%d-%d' % (j*stat_step,
                            (j+1)*stat_step)
                    else :
                        stat_name = base_stat_name + '::' + '%d' % (j*stat_step)

                    #print stat_name
                    stat = Stat(bench, stat_name, configurations[0], stat_mode)
                    data[i,j] = stat.data()
                    #print data[i,j]
                
#                chart.xticks.append(bench)
                chart.legend.append(bench)

            draw = True

        if drawing_options[1] == 'SSMPA':

            statistics = drawing_options[2]
            base_stat_name = statistics
            benchmark_hint = drawing_options[3]
            configgroups = drawing_options[4]
            comments = drawing_options[5]

            configgroups = configgroups.split(',')

            if len(statistics.split(',')) > 1:
                sys.exit('Only one statitics is supported in SSMP mode')

            comments = comments.split(',')

            temp = False

            if 'temp' in comments:
                temp = True

            stat_mode = comments[2]

            stat_step = 1

            chart = PlotChart()
            chart.xticks = comments

            configurations = []
            subconf_num = 0
            if comments[0] == 'inc' or comments[0] == 'powerof2':
                if len(comments) < 5:
                    sys.exit('''SSMPA option need 5 comments seperated by
                        comma, the first one is the key word 'inc or
                        powerof2',
                        the second one is the starting number, the
                        third is the ending number, the fourth is the
                        incremental step, and the final one is the
                        statistic name''')
                else:
                    stat_start = int(comments[1])
                    stat_end = int(comments[2])
                    stat_step = int(comments[3])
                    stat_suffix = comments[4]

                    if stat_suffix == 'NON':
                        stat_suffix = ''

                    subconf_num = ((stat_end - stat_start) / stat_step) + 1
                    print subconf_num
                    
                    temp_confs = []
                    for conf in configgroups:
                        if conf == 'simple_to_perfect_type_Omax':
                            num = (stat_end - stat_start) /\
                                    stat_step + 1
                            temp_confs.append([conf]*num)
                        elif comments[0] == 'inc':
                            temp_confs.append([conf + '_' + str(i) + \
                                stat_suffix for i in\
                                range(stat_start, stat_end + 1, stat_step)])

                            if temp:
                                chart.xticks = [str(2**(i+4)) + stat_suffix for i in \
                                                    range(stat_start, \
                                                          stat_end + 1, \
                                                          stat_step)]
                                continue

                            chart.xticks = [str(i) + stat_suffix for i in\
                                    range(stat_start, stat_end + 1, stat_step)]
                        elif comments[0] == 'powerof2':
                            temp_confs.append([conf + '_' + str(2**i)\
                                + stat_suffix for i in \
                                range(stat_start, stat_end + 1, stat_step)])

                            chart.xticks = [str(2**i) + stat_suffix for i in\
                                    range(stat_start, stat_end + 1, stat_step)]

                    configurations = temp_confs

                    print chart.xticks

            else:
                sys.exit('''SSMPA need keyword of inc or powerof2''')

            benchmarks = []
            if benchmark_hint == 'all' :
                benchmarks = int_benchmarks + float_benchmarks 
            elif benchmark_hint == 'int':
                benchmarks = int_benchmarks
            elif benchmark_hint == 'fp':
                benchmarks = float_benchmarks 
            else :
                benchmarks = benchmark_hint.split(',')

            confgroup_num = len(configgroups)

            data = np.zeros(confgroup_num * subconf_num)
            extra = np.zeros(confgroup_num * subconf_num)
            
            data.shape = (confgroup_num, subconf_num)
            extra.shape = (confgroup_num, subconf_num)

#            chart.xticks = []
            chart.legend = comments[5:5 + confgroup_num]
#            print chart.legend
            chart.xlabel = unicode(comments[-2].replace('_', ' '), 'utf-8')
            chart.ylabel = unicode(comments[-3].replace('_', ' '), 'utf-8')
#            chart.xlabel = u"资源"
#            print "%s" % chart.xlabel

            print "Drawing %s for %s" % (base_stat_name, benchmark_hint)

#            chart.xticks = comments

            for i,conf in enumerate(configurations):

                for j,subconf in enumerate(conf):

                    if temp:
                        data[i,j] = (TempStat('', j + 1, subconf)).data()
                        print data[i,j]
                        continue

#                    print subconf

                    temp_data = np.zeros(len(benchmarks))

                    for k,bench in enumerate(benchmarks):

                        if statistics == 'mpki':
                            mispredicts = Stat(bench,
                                    'system.cpu.commit.branchMispredicts', 
                                    subconf,
                                    'normal')
                            commit_insts = Stat(bench,
                                    'system.cpu.committedInsts_total',
                                    subconf,
                                    'normal')
                            temp_data[k] = mispredicts.data() /\
                                (commit_insts.data() / 1000.0)
                        elif statistics == 'mpki_exit':
                            mispredicts = Stat(bench,
                                               'system.cpu.commit.exitMispredicts', 
                                               subconf,
                                               'normal')
                            commit_insts = Stat(bench,
                                                'system.cpu.committedInsts_total',
                                                subconf,
                                                'normal')
                            temp_data[k] = mispredicts.data() /\
                                    (commit_insts.data() / 1000.0)
                        elif statistics == 'mpki_type':
                            mispredicts = Stat(bench,
                                               'system.cpu.commit.branchTypeOnlyMispredicts', 
                                               subconf,
                                               'normal')
                            commit_insts = Stat(bench,
                                                'system.cpu.committedInsts_total',
                                                subconf,
                                                'normal')
                            temp_data[k] = mispredicts.data() /\
                                    (commit_insts.data() / 1000.0)

                        else :
                            stat = Stat(bench,
                                    statistics, 
                                    subconf,
                                    'normal')
                            temp_data[k] = stat.data()

#                        print temp_data[k]

                    data[i,j] = ArithmaticMean(temp_data)
#                    data[i,j] = GeometryMean(temp_data)
#                    print conf
#                    print subconf
#                    print data[i,j]

#                chart.legend.append(configgroups[i])

            draw = True

            configurations[0] = configgroups[0]
            configurations[1] = configgroups[1]
 
        if draw:
            chart.data = data
            chart.fig_legend = None
            chart.legend_loc = 'best'
#            chart.xstep = stat_step
            chart.legend_size = 10.5
            chart.figure_size = [0.12,0.16,0.84,0.8]
#            chart.figure_size = [0.12,0.18,0.62,0.8]
#            chart.chart_size = [4,2.625]
#            chart.chart_size = [6,3.9378]
            chart.chart_size = [4.5,2.95335]
            chart.xlabel_rotation = 0
            chart.colormap = 'prism'
            chart.ygrid = True
            chart.graph()

            fname = re.sub(':','--',base_stat_name)
            fname = re.sub('\.','-',fname)
#            fname = fname + '-' + configurations[0] + '-'\
#                    + re.sub(',', '-', benchmark_hint) 
            fname = comments[-1]
            
            chart.savefig(joinpath(output_dir, 'png', fname + '.png'))
            chart.savefig(joinpath(output_dir, 'pdf', fname + '.pdf'))
#            chart.savefig(joinpath(output_dir, 'eps', fname + '.eps'))
#            chart.savefig(joinpath(output_dir, 'ps', fname + '.ps'))
            chart.savecsv(joinpath(output_dir, 'csv', fname + '.csv'))

